// 版权归陈超所有


#include "AbilitySystem/CC_AttributeSet.h"

#include "AbilitySystemBlueprintLibrary.h"
#include "CC_GameplayTags.h"
#include "Net/UnrealNetwork.h"
#include "GameplayEffectExtension.h"  // 包含FGameplayEffectModCallbackData定义
#include "GameFramework/Character.h"


UCC_AttributeSet::UCC_AttributeSet()
{
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Agile, GetAgileAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Intelligence, GetIntelligenceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Strength, GetStrengthAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Vigor, GetVigorAttribute);
	
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_Armor, GetArmorAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_ArmorPenetration, GetArmorPenetrationAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_BlockChance, GetBlockChanceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_CriticalHitChance, GetCriticalHitChanceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_CriticalHitDamage, GetCriticalHitDamageAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_CriticalHitResistance, GetCriticalHitResistanceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_HealthRegeneration, GetHealthRegenerationAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_ManaRegeneration, GetManaRegenerationAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_MaxHealth, GetMaxHealthAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_MaxMana, GetMaxManaAttribute);

}

void UCC_AttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
	Super::PreAttributeChange(Attribute, NewValue);

	if (Attribute == GetHealthAttribute())
	{
		NewValue = FMath::Clamp(NewValue, 0.f, GetMaxHealth());
	}
	if (Attribute == GetManaAttribute())
	{
		NewValue = FMath::Clamp(NewValue, 0.f, GetMaxMana());
	}
}

void UCC_AttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
{
	Super::PostGameplayEffectExecute(Data);
	
	FEffectProperties Props;
	SetEffectProperties(Data, Props);
	
	if(Data.EvaluatedData.Attribute == GetHealthAttribute())
	{
		SetHealth(FMath::Clamp(GetHealth(), 0.f, GetMaxHealth()));
	}

	if(Data.EvaluatedData.Attribute == GetManaAttribute())
	{
		SetMana(FMath::Clamp(GetMana(), 0.f, GetMaxMana()));
	}
	
}

void UCC_AttributeSet::SetEffectProperties(const struct FGameplayEffectModCallbackData& Data, FEffectProperties& Props) const
{
	Props.EffectContextHandle = Data.EffectSpec.GetContext();
	
	//获取效果所有者的相关对象
	Props.SourceASC = Props.EffectContextHandle.GetOriginalInstigatorAbilitySystemComponent();	//获取SourceASC
	if(IsValid(Props.SourceASC) && Props.SourceASC->AbilityActorInfo.IsValid() && Props.SourceASC->AbilityActorInfo->AvatarActor.IsValid())
	{
		Props.SourceAvatarActor = Props.SourceASC->AbilityActorInfo->AvatarActor.Get();			//获取SourceAvatarActor
		Props.SourceController = Props.SourceASC->AbilityActorInfo->PlayerController.Get();		//获取SourceController
		if(Props.SourceController == nullptr && Props.SourceAvatarActor != nullptr)
		{
			if(const APawn* Pawn = Cast<APawn>(Props.SourceAvatarActor))
			{
				Props.SourceController = Pawn->GetController();
			}
		}

		if(Props.SourceController)
		{
			Props.SourceCharacter = Cast<ACharacter>(Props.SourceController->GetPawn());	//获取SourceCharacter
		}
	}

	if(Data.Target.AbilityActorInfo.IsValid() && Data.Target.AbilityActorInfo->AvatarActor.IsValid())
	{
		Props.TargetAvatarActor = Data.Target.AbilityActorInfo->AvatarActor.Get();
		Props.TargetController = Data.Target.AbilityActorInfo->PlayerController.Get();
		Props.TargetCharacter = Cast<ACharacter>(Props.TargetAvatarActor);
		Props.TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Props.TargetAvatarActor);
	}	
}

//将游戏玩法属性添加到属性集源文件中的GetLifetimeReplicatedProps函数中
void UCC_AttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	
	// 为生命值添加复制功能。
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Health, COND_None, REPNOTIFY_Always);
	// 为最大生命值添加复制功能。
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, MaxHealth, COND_None, REPNOTIFY_Always);
	// 为魔法值添加复制功能。
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Mana, COND_None, REPNOTIFY_Always);
	// 为最大魔法值添加复制功能。
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, MaxMana, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Intelligence, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Agile, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Strength, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Vigor, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Armor, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, ArmorPenetration, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, BlockChance, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, CriticalHitChance, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, CriticalHitDamage, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, CriticalHitResistance, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, HealthRegeneration, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, ManaRegeneration, COND_None, REPNOTIFY_Always);
	
}

void UCC_AttributeSet::OnRep_ManaRegeneration(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, ManaRegeneration, OldValue);
}

void UCC_AttributeSet::OnRep_HealthRegeneration(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, HealthRegeneration, OldValue);
}

void UCC_AttributeSet::OnRep_CriticalHitResistance(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, CriticalHitResistance, OldValue);
}

void UCC_AttributeSet::OnRep_CriticalHitDamage(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, CriticalHitDamage, OldValue);
}

void UCC_AttributeSet::OnRep_CriticalHitChance(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, CriticalHitChance, OldValue);
}

void UCC_AttributeSet::OnRep_BlockChance(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, BlockChance, OldValue);
}

void UCC_AttributeSet::OnRep_ArmorPenetration(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, ArmorPenetration, OldValue);
}

void UCC_AttributeSet::OnRep_Armor(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Armor, OldValue);
}

//~Begin 属性复制回调函数
void UCC_AttributeSet::OnRep_Health(const FGameplayAttributeData& OldValue) const
{
	// 使用默认的游戏玩法属性系统更新通知行为。
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Health, OldValue);
}

void UCC_AttributeSet::OnRep_MaxHealth(const FGameplayAttributeData& OldValue) const
{
	// 使用默认的游戏玩法属性系统更新通知行为。
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, MaxHealth, OldValue);
}

void UCC_AttributeSet::OnRep_Mana(const FGameplayAttributeData& OldValue) const
{
	// 使用默认的游戏玩法属性系统更新通知行为。
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Mana, OldValue);
}

void UCC_AttributeSet::OnRep_MaxMana(const FGameplayAttributeData& OldValue) const
{
	// 使用默认的游戏玩法属性系统更新通知行为。
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, MaxMana, OldValue);
}

void UCC_AttributeSet::OnRep_Intelligence(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Intelligence, OldValue);
}

void UCC_AttributeSet::OnRep_Agile(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Agile, OldValue);
}

void UCC_AttributeSet::OnRep_Strength(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Strength, OldValue);
}

void UCC_AttributeSet::OnRep_Vigor(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Vigor, OldValue);
}

//~End 属性复制回调函数

